#include "hal_timer.h"

#ifdef CX_HAL_TIMER_ENABLE_INTERRUPT_MANAGER
timer_intr_cb_t intr_tmr1, intr_tmr2, intr_tmr3, intr_tmr4, intr_tmr5, intr_tmr9, intr_tmr10, intr_tmr11;
#endif

cx_err_t cx_hal_timer_cmd(cx_hal_timer_handle_t *handle,cx_FunctionalState_t cx_State)
{
    if(cx_State != CX_DISABLE)
    {
        tmr_counter_enable(handle->controller, TRUE);
    }
    else
    {
        tmr_counter_enable(handle->controller, FALSE);
    }
    return CX_ERR_OK;
}


cx_err_t cx_hal_timer_set_period(cx_hal_timer_handle_t *handle,cx_uint32_t Hz)
{
    uint32_t psc;
    cx_err_t ret;
    psc = handle->clock_in / handle->counterPerPeriod * Hz;
    if(psc > 65536)
    {
        ret = CX_ERR_OVF;
    }
    else
    {
        handle->controller->div = psc-1;
        ret = CX_ERR_OK;
    }
    return ret;
}

#ifdef CX_HAL_TIMER_ENABLE_INTERRUPT_MANAGER
#define TIMER_INTR_INIT(tmrx) \
(intr_tmr##tmrx).member.update = nop_intr_cb; \
(intr_tmr##tmrx).member.hall = nop_intr_cb; \
(intr_tmr##tmrx).member.trigger = nop_intr_cb 
cx_err_t cx_hal_timer_intr_init(void)
{
    TIMER_INTR_INIT(1);
    TIMER_INTR_INIT(2);
    TIMER_INTR_INIT(3);
    TIMER_INTR_INIT(4);
    TIMER_INTR_INIT(5);
    TIMER_INTR_INIT(9);
    TIMER_INTR_INIT(10);
    TIMER_INTR_INIT(11);

    return CX_ERR_OK;
}

cx_err_t cx_hal_timer_attachInterrupt(cx_hal_timer_handle_t *handle, cx_intr_cb_t cb, cx_hal_timer_intr_t cx_hal_timer_intr_type)
{
    tmr_type *tmr = handle->controller;
    timer_intr_cb_t *obj = CX_NULL;
    cx_uint32_t interrupt_type;
    cx_err_t ret = CX_ERR_OK;
    if(tmr == TMR1)
    {
        obj = &intr_tmr1;
    }
    else if(tmr == TMR2)
    {
        obj = &intr_tmr2;
    }
    else if(tmr == TMR3)
    {
        obj = &intr_tmr3;
    }
    else if(tmr == TMR4)
    {
        obj = &intr_tmr4;
    }
    else if(tmr == TMR5)
    {
        obj = &intr_tmr5;
    }

    else if(tmr == TMR9)
    {
        obj = &intr_tmr9;
    }
    else if(tmr == TMR10)
    {
        obj = &intr_tmr10;
    }
    else if(tmr == TMR11)
    {
        obj = &intr_tmr11;
    }
    switch(cx_hal_timer_intr_type)
    {
        case CX_HAL_TIMER_INTR_UPDATE:interrupt_type = TMR_OVF_INT;break;
        case CX_HAL_TIMER_INTR_TRIGGER:interrupt_type = TMR_TRIGGER_INT;break;
        case CX_HAL_TIMER_INTR_HALL:   interrupt_type = TMR_HALL_INT;break;
        default:break;
    }
    if(obj->group[cx_hal_timer_intr_type] == nop_intr_cb)
    {
        obj->group[cx_hal_timer_intr_type] = cb;
        tmr_interrupt_enable(handle->controller, interrupt_type, TRUE);
        tmr_flag_clear(handle->controller, interrupt_type);
    }
    else
    {
        ret = CX_ERR_CONFLICT;
    }
	return ret;
}

cx_err_t cx_hal_timer_detachInterrupt(cx_hal_timer_handle_t *handle, cx_hal_timer_intr_t cx_hal_timer_intr_type)
{
    tmr_type *tmr = handle->controller;
    timer_intr_cb_t *obj = CX_NULL;
    cx_uint32_t interrupt_type;
    if(tmr == TMR1)
    {
        obj = &intr_tmr1;
    }
    else if(tmr == TMR2)
    {
        obj = &intr_tmr2;
    }
    else if(tmr == TMR3)
    {
        obj = &intr_tmr3;
    }
    else if(tmr == TMR4)
    {
        obj = &intr_tmr4;
    }
    else if(tmr == TMR5)
    {
        obj = &intr_tmr5;
    }

    else if(tmr == TMR9)
    {
        obj = &intr_tmr9;
    }
    else if(tmr == TMR10)
    {
        obj = &intr_tmr10;
    }
    else if(tmr == TMR11)
    {
        obj = &intr_tmr11;
    }
    switch(cx_hal_timer_intr_type)
    {
        case CX_HAL_TIMER_INTR_UPDATE:interrupt_type = TMR_OVF_INT;break;
        case CX_HAL_TIMER_INTR_TRIGGER:interrupt_type = TMR_TRIGGER_INT;break;
        case CX_HAL_TIMER_INTR_HALL:   interrupt_type = TMR_HALL_INT;break;
        default:break;
    }
    obj->group[cx_hal_timer_intr_type] = nop_intr_cb;
    tmr_interrupt_enable(handle->controller, interrupt_type, FALSE);
    return CX_ERR_OK;
}

#endif
